Link to this headingWeb Sockets

  • A heartbeat is built in to the protocol
  • Uses the wss:// or ws:// schema
  • Do not tunnel other services though this because it would allow services to preform XSS attacks
    • Websockets do not respect CORS

Link to this headingHandshake

Initial Upgrade Request:

GET /?encoding=text HTTP/1.1 Host: echo.websocket.org User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0 Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate, br Sec-WebSocket-Version: 13 Origin: https://www.websocket.org Sec-WebSocket-Extensions: permessage-deflate Sec-WebSocket-Key: 9lzQkbbAscpmOiwYWVSgMg== DNT: 1 Connection: keep-alive, Upgrade Sec-Fetch-Dest: websocket Sec-Fetch-Mode: websocket Sec-Fetch-Site: same-site Pragma: no-cache Cache-Control: no-cache Upgrade: websocket

Initial Upgrade Response:

HTTP/1.1 101 Web Socket Protocol Handshake Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: content-type Access-Control-Allow-Headers: authorization Access-Control-Allow-Headers: x-websocket-extensions Access-Control-Allow-Headers: x-websocket-version Access-Control-Allow-Headers: x-websocket-protocol Access-Control-Allow-Origin: https://www.websocket.org Connection: Upgrade Date: Mon, 15 Mar 2021 21:32:46 GMT Sec-WebSocket-Accept: H82Hn1AbYRO3N7uzo6yysC0KdM0= Server: Kaazing Gateway Upgrade: websocket

Link to this headingWebSocket-Key

The Sec-WebSocket-Accept value is generated from the initial key sent from the client and a static value in the RFC.

Generating the Sec-WebSocket-Accept:

import hashlib, base64 Static_Value = b'258EAFA5-E914-47DA-95CA-C5AB0DC85B11' WebSocket_Key = b'9lzQkbbAscpmOiwYWVSgMg==' out = hashlib.sha1(WebSocket_Key + Static_Value).digest() print(base64.b64encode(out)) #b'H82Hn1AbYRO3N7uzo6yysC0KdM0='

Link to this headingURL Parsing

  • Web Socket URLs parse different from HTTP URLs
import urlparse print(urlparse.urlparse('wss://foo/?bar=baz')) #ParseResult(scheme='wss', netloc='foo', path='/?bar=baz', params='', query='', fragment='')

F:\Memory\Web Exploitation\Technologies\Web Sockets.md

Link to this headingAuthentication/Authorization

  • There is no authentication in the Protocol. The application must use TLS, [HTTP Headers](/Web Exploitation/HTTP Headers.md) or Cookies to authenticate.
  • Need to Connect the Client IP to the account that requested the Websocket Upgrade.

Link to this headingOrigin Header

  • Not restrained by Cross Origin Policy
    • Origin is sent in the Upgrade request
    • Make sure that the Server limits the allowed origins by checking the Origin Header in the Upgrade request
    • If this is not set then an attacker can so Cross Origin WebSockets. This includes sending request and getting responses responses

Link to this headingFraming

Source RFC

Link to this headingTunneling

Link to this headingSecurity

Link to this headingAuthentication/Authorization

Access Control:

Link to this headingCross-Site WebSocket Hijacking (CSWSH)

Websockets are not restricted by Cross Origin Policy. You can make a Websocket from another domain and this will send cookies alongside with it. This is up to the server to restrict.

Example CSWSH Request:

GET /v3/channel_1?api_key=VCXCEuvhGcBDP7XhiJJUDvR1e1D3eiVjgZ9VRiaV&notify_self HTTP/1.1 Host: demo.piesocket.com User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:100.0) Gecko/20100101 Firefox/100.0 Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Sec-WebSocket-Version: 13 Origin: http://livepersoninc.github.io Sec-WebSocket-Key: B65ortnvry9gUVYWTRJ+YQ== Connection: keep-alive, Upgrade Cookie: _gcl_au=1.1.1222441835.1654180959; _ga=GA1.2.1857463516.1654180960; _gid=GA1.2.265480995.1654180960; _fbp=fb.1.1654180960477.1170827820 Sec-Fetch-Dest: websocket Sec-Fetch-Mode: websocket Sec-Fetch-Site: cross-site Pragma: no-cache Cache-Control: no-cache Upgrade: websocket

Example CSWSH Response

HTTP/1.1 101 Switching Protocols Date: Thu, 02 Jun 2022 14:46:12 GMT Connection: upgrade Upgrade: websocket Sec-WebSocket-Accept: KsM7mIwWmDR0JLRLdXQ3TtvS18E= X-Powered-By: Ratchet/0.4.4

Source

Link to this headingTesting

Web Socket Tester:

<html> <head> <title>WebSocket Tester</title> </head> <body> <h2>WebSocket Tester</h2> Target: <input type="text" id="target" value="" /> <br /> <button id="connect">Connect</button> <button id="disconnect">Disconnect</button> <br /> <br />Message: <input type="text" id="message" value="" /> <button id="send">Send</button> <br /> <br />Output: <br /> <pre><div id="output"></div></pre> <script language="javascript" type="text/javascript"> var websocket; var ping; //Setup var connect = document.getElementById('connect') var disconnect = document.getElementById('disconnect') //Callback Functions function doConnect() { websocket = new WebSocket( document.getElementById("target").val() ); websocket.onopen = function (evt) { onOpen(evt) var ping = setInterval(function () { doPing() }, 1000); }; websocket.onclose = function (evt) { onClose(evt) }; websocket.onmessage = function (evt) { onMessage(evt) }; websocket.onerror = function (evt) { onError(evt) }; } function doDisconnect() { websocket.close(); } function onOpen(evt) { writeToScreen("CONNECTED"); } function onClose(evt) { writeToScreen("DISCONNECTED"); } function onMessage(evt) { if ((evt.data != "ping") && (evt.data != "pong")) { writeToScreen('RECIEVED: ' + evt.data); } } function onError(evt) { writeToScreen('ERROR:' + evt.data); } function doSend(message) { if (message != "ping") { writeToScreen('SENT: ' + message); } websocket.send(message); } function writeToScreen(message) { var output = document.getElementById("output") output.append(message + '<br /><br />'); } function doPing() { if (websocket != "undefined") { doSend("ping"); } } connect.addEventListener("click", doConnect); disconnect.addEventListener("click", doDisconnect); var send = document.getElementById('send') send.addEventListener("click", function () { doSend( $('#message').val() ) }); </script> </body> </html>

Testing Script:

python3 ws_tester.py -u wss://example.com -m unauthed-ws.txt -w IFUZZ:./SecLists/Fuzzing/numeric-fields-only.txt -w SFUZZ:./SecLists/Fuzzing/fuzz-Bo0oM.txt -s COUNT:count

Testing Script2:

python3 ws_tester.py -u wss://example.com -m unauthed-ws.txt -w IFUZZ:/./SecLists/Fuzzing/numeric-fields-only.txt -w SFUZZ:./SecLists/Fuzzing/fuzz-Bo0oM.txt -s COUNT:count -s 87331041:checksum -s TxxxxxxxxxOxxxxxxxxxxKxxxxxxxExxxxxxxxN:token